[ Prev Page | Goto Content | Next Page ]
=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\=/=\
;; socket coding on asm/x86 ;;
Как юзать сокеты на асме? В регистр %eax суём $102 (номер вызова socketcall).
Далее, в %ebx идёт номер функции для работы с сокетом. А в %ecx кладём адрес, по
которому лежат аргументы.
Номера функций для socketcall'a ():
#define SYS_SOCKET 1 /* sys_socket(2) */
#define SYS_BIND 2 /* sys_bind(2) */
#define SYS_CONNECT 3 /* sys_connect(2) */
#define SYS_LISTEN 4 /* sys_listen(2) */
#define SYS_ACCEPT 5 /* sys_accept(2) */
#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
#define SYS_SEND 9 /* sys_send(2) */
#define SYS_RECV 10 /* sys_recv(2) */
#define SYS_SENDTO 11 /* sys_sendto(2) */
#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
Каждый аргумент имеет длину 4 байта (тип long), и соответственно самый перый
должен лежать на самом верху. Пример:
pushl $0 # INADDR_ANY
pushw $0x3500 # port
pushw $2 # AF_INET
movl %esp,%edx
И вот что мы получаем в памяти:
0x02 0x00 # word family = AF_INET
0x00 0x35 # word port = 53
0x00 0x00 0x00 0x00 # long s_addr = INADDR_ANY
Кстати, структуру sockaddr лучше создавать впрямо в стеке-по крайней мере, это
позволит избавиться от лишних ошибок. Длина структуры всегда 16 байт ! Тоесть мы
имеем первые 2 байта для хранения семейства сокета (в нашем случае AF_INET=2), а
всё остальное заполянем нулями и используем столько, сколько нужно данному типу
сокетов. Тоесть нам нужно только 6 байт.
Вот все типы сокетов в 2.4.x :
#define AF_UNSPEC 0
#define AF_UNIX 1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX */
#define AF_APPLETALK 5 /* AppleTalk DDP */
#define AF_NETROM 6 /* Amateur Radio NET/ROM */
#define AF_BRIDGE 7 /* Multiprotocol bridge */
#define AF_ATMPVC 8 /* ATM PVCs */
#define AF_X25 9 /* Reserved for X.25 project */
#define AF_INET6 10 /* IP version 6 */
#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
#define AF_DECnet 12 /* Reserved for DECnet project */
#define AF_NETBEUI 13 /* Reserved for 802.2LLC project */
#define AF_SECURITY 14 /* Security callback pseudo AF */
#define AF_KEY 15 /* PF_KEY key management API */
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET 17 /* Packet family */
#define AF_ASH 18 /* Ash */
#define AF_ECONET 19 /* Acorn Econet */
#define AF_ATMSVC 20 /* ATM SVCs */
#define AF_SNA 22 /* Linux SNA Project (nutters!) */
#define AF_IRDA 23 /* IRDA sockets */
#define AF_PPPOX 24 /* PPPoX sockets */
#define AF_MAX 32 /* For now.. */
Всякие PF_INET,PF_UNIX,etc просто ссылаются на эти значения,так что это всегда
одно и то же.
Для создания сокета (для вызова sys_socket()) нам нужно знать помимо семейства
сокета его тип и протокол.
Типы сокетов :
#define SOCK_STREAM 1 /* stream (connection) socket */
#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
#define SOCK_RAW 3 /* raw socket */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequential packet socket */
#define SOCK_PACKET 10 /* linux specific way of */
А тут перечислены все основные протоколы ():
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
IPPROTO_PUP = 12, /* PUP protocol. */
IPPROTO_UDP = 17, /* User Datagram Protocol. */
IPPROTO_IDP = 22, /* XNS IDP protocol. */
IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */
IPPROTO_IPV6 = 41, /* IPv6 header. */
IPPROTO_ROUTING = 43, /* IPv6 routing header. */
IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
IPPROTO_RSVP = 46, /* Reservation Protocol. */
IPPROTO_GRE = 47, /* General Routing Encapsulation. */
IPPROTO_ESP = 50, /* encapsulating security payload. */
IPPROTO_AH = 51, /* authentication header. */
IPPROTO_ICMPV6 = 58, /* ICMPv6. */
IPPROTO_NONE = 59, /* IPv6 no next header. */
IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */
IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
IPPROTO_ENCAP = 98, /* Encapsulation Header. */
IPPROTO_PIM = 103, /* Protocol Independent Multicast. */
IPPROTO_COMP = 108, /* Compression Header Protocol. */
IPPROTO_RAW = 255, /* Raw IP packets. */
IPPROTO_MAX
А вот и пример проги, работающей с raw-сокетами:
.globl _start
_start:
subl $0x20,%esp # обнуляем 32 байта в стеке
# sock =socket(AF_INET,SOCK_RAW,IPPROTO_UDP)
xorl %eax,%eax
movl $2,(%esp) # AF_INET
movl $3,0x4(%esp) # SOCK_RAW
movl $17,0x8(%esp) # UDP proto
movl %esp,%ecx # кладём адрес аргументов в %ecx
movl $1,%ebx # sys_socket()
mov $102,%al # sys_socketcall()
int $128
movl %eax,%edx # сохраняем сокет в %edx, т.к. он не используется
# setsockopt(sock,SOL_IP,IP_HDRINCL,(char *) &optval, 4)
movl %edx,(%esp) # указатель на наш сокет
movl $0,0x4(%esp) # SOL_IP
movl $3,0x8(%esp) # IP_HDRINCL = 3 (g0t0 )
movl $optval,0xc(%esp) # value
movl $4,0x10(%esp) # 4 байта, т.к. optval это адрес
movl $14,%ebx # sys_setsockopt()
movl $102,%eax # sys_socketcall()
int $128
# sendto(sock,rawpacket,sizeof(rawpacket),0,(struct sockaddr *) &suck,16)
movl %edx,(%esp) # указатель
movl $rawpacket,0x4(%esp) # адрес, по которому лежит пакет
movl $30,0x8(%esp) # размер пакета
movl $0,0xc(%esp) # flags 0
# начинаем заполнять структуру sockaddr:
movw $2,0x18(%esp) # family = AF_INET
movw $0x3500,0x1a(%esp) # port 53
movl $0x0100007f,0x1c(%esp) # dst ip: 127.0.0.1
# всё остальное пространство в после daddr мы заполнили нулями в самом начале,
# так что мы используем наши 8 байт, а остальное просто не трогаем.
lea 0x18(%esp),%ebx # вычисляем адерс нашей структуры sockaddr...
movl %ebx,0x10(%esp) # ...и кладём в стек 5-м аргументом
movl $16,0x14(%esp) # 6-й аргумент - размер структуры sockaddr
movl $11,%ebx # sys_sendto()
movl $102,%eax # sys_socketcall()
int $128
movl %edx,%ebx # указатель на сокет - первый аргумент
movl $6,%eax # close() syscall
int $128
movl $1,%eax # exit() syscall
int $128
optval: .byte 0x13 # justa value
rawpacket:
.ascii "\x45" # ver=4; ihl=5
.ascii "\x9f" # tos bits = 10011110 (wrrr000mm!!)
.ascii "\x00\x30" # tot_len
.ascii "\x32\x8f" # id
.ascii "\x40\x00" # flags
.ascii "\xff" # ttl
.ascii "\x11" # udp proto
.ascii "\x00\x00" # ip header checksum - заполняется ядром
.ascii "\x0d\x06\x06\x06" # src ip: 13.6.6.6
.ascii "\x7f\x00\x00\x01" # dst ip: 127.0.0.1
# udp header:
.ascii "\x00\x35" # src port 53
.ascii "\x00\x35" # dst port 53
.ascii "\x00\x0a" # udp + payload len
.ascii "\xa0\x63" # udp + payload checksum
# ma small payload:
.ascii "\x61\x0a" # aka "a\n"
Вот собственно и всё, что хотелось сказать. И на последок пара трюков:
[hint 1]: для SOL_TCP (sock object level для протокола TCP) есть одна интересная
опция TCP_NODELAY. Она отключает буферизацию инфы, и следовательно
обработчик tcp-пакетов будет сразу слать полученные данные проге. Так
можно немного ускорить/улучшить соединение.
[hint 2]: используя TOS можно добиться того, что роутеры, поддерживающие данные
режимы будут скажем быстрее обрабатывать наши пакеты. Вот формат tos:
bits: 0--1--2--3--4--5--6--7
A A A B C D E 0
AAA (первые три бита) - приоритет датаграммы. Значения:
111 - управление сетью ( heh, hypa-speed? ;)
110 - межсетевое управление
101 - CRITIC-ECP
100 - более чем мгновенно (what da nice shit)
011 - мгновенно
010 - немедленно
001 - срочно
000 - обчно
B (1 бит) - выбор маршрута с минимальной задержкой
С (1 бит) - выбор маршрута с максимальной пропускной способносью
D (1 бит) - выбор маршрута с максимальной надёжностью
E (1 бит) - выбор маршрута с минимальной стоимостью
Удачных эксперементов!
[ Prev Page | Goto Content | Next Page ]